<?php
///////////////////////////////////////////////////////////////////////////////////////////////////////
//  这个文件是 JCAT PHP框架的一部，该项目和此文件 均遵循 GNU 自由软件协议
// 
//  Copyleft 2008 JeCat.cn(http://team.JeCat.cn)
//
//
//  JCAT PHP框架 的正式全名是：Jellicle Cat PHP Framework。
//  “Jellicle Cat”出自 Andrew Lloyd Webber的音乐剧《猫》（《Prologue:Jellicle Songs for Jellicle Cats》）。
//  JCAT 是一个开源项目，它像音乐剧中的猫一样自由，你可以毫无顾忌地使用JCAT PHP框架。
//  JCAT 由中国团队开发维护，是一个国际性的项目。
//  正在使用的这个版本是：0.3.1 / SVN信息：$Id: class.JCAT_LanguagePackage.php 1119 2008-10-25 03:55:26Z alee $
//
//
//
//  相关的链接：
//    [主页] http://jcat.JeCat.cn
//    [HTTP下载] http://jcat.JeCat.cn/download
//    [在线文档] http://jcat.JeCat.cn/document
//    [社区] http://jj.jecat.cn/forum-7-1.html
//  不很相关：
//    [MP3] http://www.google.cn/search?q=jellicle+songs+for+jellicle+cats+Andrew+Lloyd+Webber
//    [VCD/DVD] http://www.google.cn/search?q=CAT+Andrew+Lloyd+Webber+video
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
/*-- Project Introduce --*/


/**
 * 语言包
 *
 * @author		alee
 * @access		public
 */
class JCAT_LanguagePackage
{

	/**
	 * 添加一个语言包目录
	 * 
	 * @access	public
	 * @param	$sPath	string	目录路径
	 * @static
	 * @return	void
	 */
	static public function AddPackageDir( $sPath ) 
	{
		JCAT_ASSERT::ASSERT_DIR($sPath,'参数 $sPath 必须是有效的目录。') ;

		$sPath = JCAT_Global::TidyPath($sPath) ;
		
		if( !in_array($sPath,self::$arrLanguagePackageDis) )
		{
			self::$arrLanguagePackageDis[] = $sPath ;
		}
	}



	/**
	 * 清空语言包目录
	 * 
	 * @access	public
	 * @static
	 * @return	void
	 */
	static public function ClearPackageDir() 
	{
		self::$arrLanguagePackageDis = array() ;
	}


	/**
	 * 取得一个语言包享员对象
	 * 
	 * @access	public
	 * @param	$sPackageName		string	语言包名称 
	 * @param	$sLanguageName=''	string	语言名称
	 * @return	string
	 */
	static public function GetPackage( $sLanguageName, $sPackageName ) 
	{
		// 直接返回已经被创建的享员对象
		if( isset(self::$arrLanguagePackageInses[ $sLanguageName ][ $sPackageName ]) )
		{
			return self::$arrLanguagePackageInses[ $sLanguageName ][ $sPackageName ] ;
		}
		
		// 创建对象
		else 
		{
			$thePackage = null ;
			foreach(self::$arrLanguagePackageDis as $sDir)
			{
				$sThePackagePath = self::FindPackage($sDir,$sLanguageName,$sPackageName) ;
				if(!$sThePackagePath)
				{
					continue ;
				}
				
				// 加载语言
				if($thePackage)
				{
					$thePackage->LoadPackageFile($sThePackagePath) ;
				}

				// 创建语言包对象
				else 
				{
					$thePackage = self::CreatePackage( $sLanguageName, $sPackageName, $sThePackagePath ) ;
				}
			}
			
			return $thePackage ;
		}
	}
	
	/**
	 * 根据语言包名称，在指定目录内 找到语言包
	 *
	 * @access	private
	 * @param	$sDir				string	指定目录
	 * @param	$sLanguageName	string	语言名称
	 * @param	$sPackageName		string	语言包名称 
	 * @return	string
	 * @static
	 */
	static private function FindPackage( $sDir, $sLanguageName, $sPackageName )
	{
		$sPath = "{$sDir}{$sLanguageName}.{$sPackageName}.lpg" ;
		if( is_file( $sPath ) )
		{
			return $sPath ;
		}
		
		return null ;		
	}
	
	/**
	 * 创建语言包实例
	 * 
	 * @access	private
	 * @param	$sLanguageName	string	语言名称
	 * @param	$sPackageName	string	语言包名称
	 * @param	$sPackagePath	string	语言包文件的完整路径
	 * @return	JCAT_LanguagePackage
	 */
	static private function CreatePackage($sLanguageName, $sPackageName, $sPackagePath)
	{
		// 直接返回 已创建的 语言包
		if( isset(self::$arrLanguagePackageInses[ $sLanguageName ][ $sPackageName ]) )
		{
			return self::$arrLanguagePackageInses[ $sLanguageName ][ $sPackageName ] ;
		}
		
		return self::$arrLanguagePackageInses[ $sLanguageName ][ $sPackageName ]
							 =  new self( $sLanguageName, $sPackageName, $sPackagePath ) ;
	}
	
	/**
	 * 构造函数，只能通过 self::CreatePackage() 创建
	 * 
	 * @access	public
	 * @param	$sLanguageName	string	语言名称
	 * @param	$sPackageName	string	语言包名称
	 * @param	$sPackagePath	string	语言包文件的完整路径
	 * @return	void
	 */
	private function JCAT_LanguagePackage( $sLanguageName, $sPackageName, $sPackagePath ) 
	{
		JCAT_ASSERT::ASSERT_STRING($sLanguageName,'参数 $sLanguageName 必须为字符串类型。') ;
		JCAT_ASSERT::ASSERT_STRING($sPackageName,'参数 $sName 必须为字符串类型。') ;
		JCAT_ASSERT::ASSERT_FILE($sPackagePath,'参数 $sPath 必须是有效的语言包文件。') ;
		
		$this->sPackagePath = $sPackagePath ;
		$this->sPackageName = $sPackageName ;
		$this->sLanguageName = $sLanguageName ;
		
		$this->Load() ;	
	}



	/**
	 * 析构函数
	 * 
	 * @access	public
	 * @return	void
	 */
	public function __destruct(  ) 
	{
		if( $this->IsUpdated() )
		{
			$this->Save() ;
		}
	}


	/**
	 * 返回语言包名称
	 * 
	 * @access	public
	 * @return	string
	 */
	public function GetName()
	{ return $this->sPackageName ; }

	/**
	 * 返回语言名称
	 * 
	 * @access	public
	 * @return	string
	 */
	public function GetLanguageName()
	{ return $this->sLanguageName ; }

	/**
	 * 设置一条语句
	 * 
	 * @access	public
	 * @param	$sKey		string 语句的 key
	 * @param	$sSentence	string 语句内容
	 * @return	
	 */
	public function Set( $sKey, $sSentence ) 
	{
		JCAT_ASSERT::ASSERT_STRING($sKey,'参数 $sKey 必须为字符串') ;
		JCAT_ASSERT::ASSERT_STRING($sSentence,'参数 $sSentence 必须为字符串') ;
		
		if( $this->Get($sKey)===$sSentence )
		{
			return ;
		}
			
		$this->arrSentences[$sKey] = $sSentence ;
		$this->bUpdated = true ;
	}



	/**
	 * 取回一条语句
	 * 
	 * @access	public
	 * @param	$sKey	string	语句的Key
	 * @return	
	 */
	public function Get(  $sKey ) 
	{
		JCAT_ASSERT::ASSERT_STRING($sKey,'参数 $sKey 必须为字符串') ;
		
		if( $this->Has($sKey) )
		{
			return $this->arrSentences[$sKey] ;
		}
		else
		{
			return null ;
		}
	}

	/**
	 * 检查一条语句是否存在
	 * 
	 * @access	public
	 * @param	$sKey	string	语句的 Key
	 * @return	
	 */
	public function Has(  $sKey ) 
	{ return isset($this->arrSentences[$sKey]) ; }



	/**
	 * 相对语言包文件是否改动
	 * 
	 * @access	public
	 * @return	bool
	 */
	public function IsUpdated() 
	{ return $this->bUpdated ; }



	/**
	 * 保存到语言包文件
	 * 
	 * @access	public
	 * @return	
	 */
	public function Save() 
	{
		$sOut = '<'."?\r\n" ;
		foreach($this->arrSentences as $sKey=>$sSentence)
		{
			$sSentence = str_replace('"','\\"',$sSentence) ;
			$sSentence = str_replace("\n","\\n",$sSentence) ;
			$sSentence = str_replace("\r","\\r",$sSentence) ;
			$sSentence = str_replace('$','\\$',$sSentence) ;
			$sOut.= "\$this->arrSentences['{$sKey}'] = \"$sSentence\" ;\r\n" ;
		}
		$sOut.= "\r\n?".'>' ;
		
		file_put_contents($this->sPackagePath,$sOut) ;
	}



	/**
	 * 从语言包文件中读出语句
	 * 
	 * @access	public
	 * @return	
	 */
	public function Load() 
	{
		$this->arrSentences = array() ;
		$this->LoadPackageFile($this->sPackagePath) ;
	}

	/**
	 * 从指定的语言包文件中读出语句
	 * 
	 * @access	public
	 * @param 	$sPackagePath	string
	 * @return	void
	 */
	public function LoadPackageFile($sPackagePath) 
	{
		JCAT_ASSERT::ASSERT_FILE($sPackagePath)  ;
		
		include $sPackagePath ;
		
		// 更新语言包的时间
		$nFileMTime = filemtime($sPackagePath) ;
		if( $this->nUpdateTime < $nFileMTime )
		{
			$this->nUpdateTime = $nFileMTime ;
		}
	}
	
	/**
	 * 为语句创建跌代器
	 *
	 * @access	public
	 * @return	JCAT_ArrayIterator
	 */
	public function CreateSentenceIterator()
	{
		return new JCAT_ArrayIterator($this->arrSentences) ;
	}
	
	/**
	 * 取得语言包的更新时间（该时间为所有语言包文件的最新时间）
	 *
	 * @access	public
	 * @return	int
	 */
	public function GetUpdateTime()
	{
		return $this->nUpdateTime ;
	}



	// 属性 ///////////////////////////////////////////////////////////////////////////////

	/**
	 * 语言包名称
	 * 
	 * @access	private
	 * @var		string
	 */
	private $sPackageName = '' ;
	
	/**
	 * 语言名称
	 * 
	 * @access	private
	 * @var		string
	 */
	private $sLanguageName = '' ;
	
	/**
	 * 语言包文件 的 完整路径
	 * 
	 * @access	private
	 * @var		string
	 */
	private $sPackagePath = '' ;
	
	/**
	 * 语句
	 * 
	 * @access	private
	 * @var		array
	 */
	private $arrSentences = array() ;
	
	/**
	 * 是否更新
	 * 
	 * @access	private
	 * @var		bool
	 */
	private $bUpdated = false ;
	
	/**
	 * 语言包的更新时间
	 * 
	 * @access	private
	 * @var		int
	 */
	private $nUpdateTime = 0 ;
	

	/**
	 * 语言包目录
	 * 
	 * @access	private
	 * @var		array
	 * @static
	 */
	static private $arrLanguagePackageDis = array() ;
	
	/**
	 * 所有已经载入的语言包
	 * 
	 * @access	private
	 * @var		array
	 * @static
	 */
	static private $arrLanguagePackageInses = array() ;

}
/*macro_exception_code:0*/
?>